package fileIO;

import java.io.*;
import java.util.HashMap;
import java.util.Scanner;

import ModelRepresentations.Model;
import ModelRepresentations.ModelObject;

import updatedModels.Utils.Utils;

public class ModelReader extends AParser{
	
	public ModelReader(){
	}
	
	
	public static HashMap<String, String> readModelDataFromFile(String fileName){
		Scanner scanner = null;
		try {
			scanner = new Scanner(new File(fileName));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// scanner.useDelimiter("\\{");
		HashMap<String, String> modelData = new HashMap<String, String>();
		
		/*String temp = scanner.nextLine();
		
		
		temp = temp.replaceAll("\\{", " { ");
		temp = temp.replaceAll("\\}", " } ");
		
		String[] tempArray = temp.split("\\s+");
		
		System.out.println(tempArray[2941]);
		System.out.println(tempArray[2942]);
		System.out.println(tempArray[2943]);
		System.out.println(tempArray[2944]);
		System.out.println(tempArray[2945]);
		System.out.println(tempArray.length);/**/
		
		while(scanner.hasNext()){
			// read a key-value pair and place it in the hashmap
			String tempKey = scanner.next();
			if(scanner.hasNext()){
				String tempValue = scanner.next();
				System.out.println(tempKey + tempValue);
				modelData.put(tempKey, tempValue);
			}
			// modelData.put(scanner.next(), scanner.next());
		}/**/
		
		return modelData;
	}
	
	
	
	
	/*
	 * Count the number of "{" and for each "{" you add one and for each "}" you subtract one.
	 */
	public Model readModelFromFile(String fileName){
		Scanner scanner = null;
		Model model = null;
		
		try {
			scanner = new Scanner(new File(fileName));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		HashMap<String, String> modelData = new HashMap<String, String>();
		
		String temp = scanner.nextLine();
		
//		temp = temp.replaceAll("http://www.omg.org/bpmn20", "www.omg.org/bpmn20");
		temp = temp.replaceAll("\\s", "_");
		temp = temp.replaceAll("\\{", " { ");
		temp = temp.replaceAll("\\}", " } ");/**/
		temp = temp.replaceAll("\\[", " [ ");
		temp = temp.replaceAll("\\]", " ] ");
		temp = temp.replaceAll("\\:", " : ");
		temp = temp.replaceAll(",", " , ");
		
		String[] tempArray = temp.split("\\s+");
		model = new Model();
//		System.out.println("entering arrayToModel with tempArray: " + tempArray[1]);
//		for(int i = 0; i < 65; i++){
//			System.out.println("tempArray = " + tempArray[i]);
//		}
		arrayToModel(model, tempArray, new int[]{0}, 0);
		
		/*while(scanner.hasNext()){
			// read a key-value pair and place it in the hashmap
			String tempKey = scanner.next();
			if(scanner.hasNext()){
				String tempValue = scanner.next();
				modelData.put(tempKey, tempValue);
			}
			// modelData.put(scanner.next(), scanner.next());
		}/**/
		
		return model;
	}
	
	
	private static boolean arrayToModel(Model model, String[] stringArray, int[] currentIndex, int numberOfBracet){
//		System.out.println("stringArray: " + stringArray.length);
		int numberOfBracets = 0;
		while(true){
			if(currentIndex[0] >= stringArray.length){
				System.out.println("returning");
				return true;
			}
			ModelObject modelObject = new ModelObject();
			
			
			// read a single modelobject if there is a modelobject otherwise add a submodel and continue reading
			
			if(stringArray[currentIndex[0]].equals("{")){ // missing "{" inside while-loop
				currentIndex[0]++;
				numberOfBracets++;
				while(true){
//					System.out.println("cur: " + stringArray[currentIndex[0]]);
					if(stringArray[currentIndex[0]].equals("{")){
						currentIndex[0]++;
						numberOfBracets++;
						modelObject = new ModelObject(); // probably overwrites the old modelobject before it is saved
					} else if(stringArray[currentIndex[0]].equals("}")){
						currentIndex[0]++;
						numberOfBracets--;
						if(numberOfBracets == 0){
//							System.out.println("breaking at " + currentIndex[0]);
//							System.out.println("with " + stringArray[currentIndex[0]-3] + " " +
//							stringArray[currentIndex[0]-2] + stringArray[currentIndex[0]-1] + " " + 
//									stringArray[currentIndex[0]]);
//							model.addModelObject(modelObject);
							break;
						} // stringArray[currentIndex[0]].equalsIgnoreCase("childShapes")
					} else if(stringArray[currentIndex[0]].equals("]")){
//						System.out.println("GOT ]");
						currentIndex[0] += 2;
						return false;
					}
					
					if(stringArray[currentIndex[0]].equals(":")){
//						System.out.println("GOT :");
						currentIndex[0]++;
					}
					if(stringArray[currentIndex[0]].equals("\"resourceId\"")){
//						System.out.println("adding resourceId");
						modelObject.setUniqueID(Utils.getUniqueID());
						modelObject.setResourceID(stringArray[currentIndex[0]+2]);
						currentIndex[0] += 4;
					}
					if(stringArray[currentIndex[0]].equals("\"properties\"")){
//						System.out.println("reading properties");
						currentIndex[0]++;
						while(true){
							if(stringArray[currentIndex[0]+1].equals(":")){
//								System.out.println("adding " + stringArray[currentIndex[0]] + " with value " + stringArray[currentIndex[0]+2]);
								modelObject.addProperties(stringArray[currentIndex[0]], stringArray[currentIndex[0]+2]);
								currentIndex[0] += 3;
							}
							else if(stringArray[currentIndex[0]].equals("}")){
								currentIndex[0] += 2;
								break;
							}else{
								currentIndex[0]++;
							}
						}
					}
					
					if(stringArray[currentIndex[0]].equals("\"stencil\"")){
//						System.out.println("stencil = " + stringArray[currentIndex[0]+5]);
						modelObject.setStencil(stringArray[currentIndex[0]+5]);
						currentIndex[0] += 8;
					}
					
					
					if(compareStrings(stringArray[currentIndex[0]], "childShapes")){
//						System.out.println("childShape");
						if((stringArray[currentIndex[0]+2].equals("[")) && (stringArray[currentIndex[0]+3].equals("]"))){
							currentIndex[0] +=5;
						}else{
							// create another model and go down one level
//							System.out.println("adding submodel");
							currentIndex[0] += 3;
							Model tempModel = new Model();
							model.addToChildren(tempModel);
							if(arrayToModel(tempModel, stringArray, currentIndex, numberOfBracets)){
//								System.out.println("returning true");
								return true;
							}
						}
					}
					
					
					if(stringArray[currentIndex[0]].equals("\"outgoing\"")){
						// enclosed within [{}], can contain several values
						currentIndex[0] += 3;
						while(true){
//							System.out.println("third while-loop");
							if(stringArray[currentIndex[0]].equals("\"resourceId\"")){
//								System.out.println("outgoing resouceId");
								modelObject.addToOutgoing(stringArray[currentIndex[0]+2]);
								currentIndex[0] += 3;
							}else if(stringArray[currentIndex[0]].equals("}") || stringArray[currentIndex[0]].equals("{")
									|| stringArray[currentIndex[0]].equals(",")){
								currentIndex[0]++;
							}else{
								currentIndex[0] += 2;
								break;
							}
						}
						
					}
					
					if(stringArray[currentIndex[0]].equals("\"bounds\"")){
						// read until matching {}
//						currentIndex[0] += 3;
						// read until two }}
						int braceCount = 1;
						currentIndex[0] += 3;
						while(braceCount > 0){
							if(stringArray[currentIndex[0]].equals("{")){
								braceCount++;
							}else if(stringArray[currentIndex[0]].equals("}")){
								braceCount--;
							}
//							System.out.println("skippingB : " + stringArray[currentIndex[0]]);
							currentIndex[0]++;
						}
						
						currentIndex[0]++;
					}
					
					// TODO: save dockers if necessary
					if(stringArray[currentIndex[0]].equals("\"dockers\"")){
						// error with }]}
						// read until matching []
						// read until }]
						int bracketCount = 1;
						currentIndex[0] += 3;
						while(bracketCount > 0){
							if(stringArray[currentIndex[0]].equals("[")){
								bracketCount++;
							}else if(stringArray[currentIndex[0]].equals("]")){
								bracketCount--;
							}
							currentIndex[0]++;
//							System.out.println("skippingD: " + stringArray[currentIndex[0]]);
						}
						currentIndex[0]++;
//						if(stringArray[currentIndex[0]].equals("}"))
//							currentIndex[0]++;
					}
					
					// always one resourceId in target it seems
					if(stringArray[currentIndex[0]].equals("\"target\"")){
						modelObject.setTarget(stringArray[currentIndex[0]+5]);
						currentIndex[0] += 8;
					}
					
					if(stringArray[currentIndex[0]].equals(",") || stringArray[currentIndex[0]].equals(" ")){
//						System.out.println("GOT , or \" \"");
						currentIndex[0]++;
					}
					
					if(stringArray[currentIndex[0]].equals("\"stencilset\"")){
//						System.out.println("found stencilset returning true");
						return true;
					}
					
					if(modelObject.getResourceID() != null && !modelObject.getResourceID().equals("")){
//						System.out.println("adding modelobject: ");
//						System.out.println(modelObject.getResourceID());
						
						model.addModelObject(modelObject);
					}
				}
					
				}else if(stringArray[currentIndex[0]].equals("]")){
//					System.out.println("Returning found ] at " + currentIndex[0]);
//					System.out.println(stringArray[currentIndex[0]-3]);
					currentIndex[0]++;
					return false;
				}else{
//					System.out.println("stringArray[currentIndex[0]] = " + stringArray[currentIndex[0]]);
					currentIndex[0]++;
				}
			}
			
			
		}
	
	
	
//	private static boolean arrayToModel(Model model, String[] stringArray, int[] currentIndex, int numberOfBracet){
////		System.out.println("stringArray: " + stringArray.length);
//		int numberOfBracets = 0;
//		while(true){
//			if(currentIndex[0] >= stringArray.length){
//				System.out.println("returning");
//				return true;
//			}
//			ModelObject modelObject = new ModelObject();
//			
//			
//			// read a single modelobject if there is a modelobject otherwise add a submodel and continue reading
//			
//			if(stringArray[currentIndex[0]].equals("{")){ // missing "{" inside while-loop
//				currentIndex[0]++;
//				numberOfBracets++;
//				while(true){
////					System.out.println("cur: " + stringArray[currentIndex[0]]);
//					
////					try {
////						Thread.sleep(100); // used for debugging
////					} catch (InterruptedException e) {
////						// TODO Auto-generated catch block
////						e.printStackTrace();
////					}
//					
////					System.out.println("first while-loop with string: " + stringArray[currentIndex[0]+2] + currentIndex[0]);
//					if(stringArray[currentIndex[0]].equals("{")){
//						currentIndex[0]++;
//						numberOfBracets++;
//						modelObject = new ModelObject(); // probably overwrites the old modelobject before it is saved
//					} else if(stringArray[currentIndex[0]].equals("}")){
//						currentIndex[0]++;
//						numberOfBracets--;
//						if(numberOfBracets == 0){
////							System.out.println("breaking at " + currentIndex[0]);
////							System.out.println("with " + stringArray[currentIndex[0]-3] + " " +
////							stringArray[currentIndex[0]-2] + stringArray[currentIndex[0]-1] + " " + 
////									stringArray[currentIndex[0]]);
////							model.addModelObject(modelObject);
//							break;
//						} // stringArray[currentIndex[0]].equalsIgnoreCase("childShapes")
//					} else if(compareStrings(stringArray[currentIndex[0]], "childShapes")){
////						System.out.println("childShape");
//						if((stringArray[currentIndex[0]+2].equals("[")) && (stringArray[currentIndex[0]+3].equals("]"))){
//							currentIndex[0] +=4;
//						}else{
//							// create another model and go down one level
//							System.out.println("adding submodel");
//							currentIndex[0] += 3;
//							Model tempModel = new Model();
//							model.addToChildren(tempModel);
//							if(arrayToModel(tempModel, stringArray, currentIndex, numberOfBracets)){
//								System.out.println("returning true");
//								return true;
//							}
//						}
//					}
//					if(stringArray[currentIndex[0]].equals(":")){
//						System.out.println("GOT :");
//						currentIndex[0]++;
//					}
//					if(stringArray[currentIndex[0]].equals("\"resourceId\"")){
////						System.out.println("adding resourceId");
//						modelObject.setResourceID(stringArray[currentIndex[0]+2]);
//						currentIndex[0] += 3;
//					}
//					if(stringArray[currentIndex[0]].equals("\"properties\"")){
////						System.out.println("reading properties");
//						currentIndex[0]++;
//						while(true){
//							if(stringArray[currentIndex[0]+1].equals(":")){
////								System.out.println("adding " + stringArray[currentIndex[0]] + " with value " + stringArray[currentIndex[0]+2]);
//								modelObject.addProperties(stringArray[currentIndex[0]], stringArray[currentIndex[0]+2]);
//								currentIndex[0] += 3;
//							}
//							else if(stringArray[currentIndex[0]].equals("}")){
//								currentIndex[0]++;
//								break;
//							}else{
//								currentIndex[0]++;
//							}
//						}
//					}
//					
//					if(stringArray[currentIndex[0]].equals("\"stencil\"")){
////						System.out.println("stencil = " + stringArray[currentIndex[0]+5]);
//						modelObject.setStencil(stringArray[currentIndex[0]+5]);
//						currentIndex[0] += 8;
//					}
//					
//					
//					if(stringArray[currentIndex[0]].equals("\"outgoing\"")){
//						// enclosed within [{}], can contain several values
//						currentIndex[0] += 3;
//						while(true){
////							System.out.println("third while-loop");
//							if(stringArray[currentIndex[0]+1].equals("\"resourceId\"")){
////								System.out.println("outgoing resouceId");
//								modelObject.addToOutgoing(stringArray[currentIndex[0]+3]);
//								currentIndex[0] += 4;
//							}else if(stringArray[currentIndex[0]].equals("}") || stringArray[currentIndex[0]].equals("{")
//									|| stringArray[currentIndex[0]].equals(",")){
//								currentIndex[0]++;
//							}else{
//								currentIndex[0]++;
//								break;
//							}
//						}
//						
//					}
//					
//					if(stringArray[currentIndex[0]].equals("\"bounds\"")){
////						currentIndex[0] += 3;
//						// read until two }}
//						while(!(stringArray[currentIndex[0]].equals("}") && stringArray[currentIndex[0]+1].equals("}"))){
//							currentIndex[0]++;
//						}
//						
//						currentIndex[0] += 2;
//					}
//					
//					// TODO: save dockers if necessary
//					if(stringArray[currentIndex[0]].equals("\"dockers\"")){
//						// error with }]}
//						// read until }]
//						while(!(stringArray[currentIndex[0]].equals("}") && stringArray[currentIndex[0]+1].equals("]"))){
//							currentIndex[0]++;
//						}
//						currentIndex[0] += 2;
////						if(stringArray[currentIndex[0]].equals("}"))
////							currentIndex[0]++;
//					}
//					
//					// always one resourceId in target it seems
//					if(stringArray[currentIndex[0]].equals("\"target\"")){
//						modelObject.setTarget(stringArray[currentIndex[0]+5]);
//						currentIndex[0] += 8;
//					}
//					
//					if(stringArray[currentIndex[0]].equals(",") || stringArray[currentIndex[0]].equals(" ")){
////						System.out.println("GOT , or \" \"");
//						currentIndex[0]++;
//					}
//					if(stringArray[currentIndex[0]].equals("]")){
//						System.out.println("GOT ]");
//						currentIndex[0]++;
//						return false;
//					}
//					
//					if(stringArray[currentIndex[0]].equals("\"stencilset\"")){
//						System.out.println("found stencilset returning true");
//						return true;
//					}
//					
//					if(modelObject.getResourceID() != null && !modelObject.getResourceID().equals("")){
//						model.addModelObject(modelObject);
//					}
//				}
//					
//				}else if(stringArray[currentIndex[0]].equals("]")){
//					System.out.println("Returning found ] at " + currentIndex[0]);
////					System.out.println(stringArray[currentIndex[0]-3]);
//					currentIndex[0]++;
//					return false;
//				}else{
////					System.out.println("stringArray[currentIndex[0]] = " + stringArray[currentIndex[0]]);
//					currentIndex[0]++;
//				}
//			}
//			
//			
//		}
	
	private static boolean compareStrings(String string1, String string2){
//		if(string1.length() != string2.length()){
//			System.out.println("not same length with " + string1.length() + " " + string2.length());
//			System.out.println(" " + string1.charAt(11) + string2.charAt(0));
//			return false;
//		}
		try{
		for(int i = 0; i < 11; i++){
			if(string1.charAt(i+1) != string2.charAt(i)){
//				System.out.println("not same chars at" + i + " with " + string1.charAt(i+1) + string2.charAt(i));
				return false;
			}
		}
		return true;
		}catch(Exception ex){
			return false;
		}
	}
		
	}
	
	
//	private static boolean arrayToModel(Model model, String[] stringArray, int[] currentIndex, int currentNodeID){
//		ModelNode currentNode = model.getNode(currentNodeID);
//		
//		while(true){
//			if(currentIndex[0] == stringArray.length){
//				return true;
//			}
//			if(stringArray[currentIndex[0]].equals("{")){
//				// go down one level
//				// check if return false/true
//				ModelNode tempNode = new ModelNode();
//				System.out.println("adding node as child to" + currentNode.getId());
//				model.addNodeAsChildTo(tempNode, currentNode);
//				currentIndex[0]++;
//				if(arrayToModel(model, stringArray, currentIndex, tempNode.getId())){
//					return true;
//				}
//			}else if(stringArray[currentIndex[0]].equals("}")){
//				currentIndex[0]++;
//				return false;
//			}else{
//				// split the string into key:value 's and add to the current modelnode
//				// model.getNode(currentNodeID).addData(key, value)
//				// probably check against "" aswell and not only against :
//				String[] tempArray = stringArray[currentIndex[0]].split(":");
//				System.out.println(stringArray[currentIndex[0]]);
//				System.out.println(currentIndex[0]);
//				for(int i = 0; i < tempArray.length-1; i += 2){
//					currentNode.addData(tempArray[i], tempArray[i+1]);
//				}
//				currentIndex[0]++;
//			}
//		}
